﻿using dotless.Core.Parser.Infrastructure.Nodes;
using Fuse8.ContentManagementFramework.Administration.Controls;
using Fuse8.ContentManagementFramework.Administration.Models;
using Fuse8.ContentManagementFramework.BizFacade.Services;
using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.SystemFacade.Common;
using Fuse8.DomainFramework.Common.Locator;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace Fuse8.ContentManagementFramework.Administration.Controllers
{
    [CmsAuthorizeAttribute]
    [FirstLoginActionFilter]
    public abstract class CmsAdminController : CmsBaseController
    {
        #region Fields

        private CmsSiteAdminMapService _siteAdminMapService;
        private CmsUserInformationService _userInformationService;
        private CmsEntityMetaInformationService _entityMetaInformationService;
        private IList<CmsSiteAdminMap> fullCmsAdminMap;

        #endregion Fields

        #region Properties

        public int DefaultPageSize
        {
            get
            {
                return 20;
            }
        }

        public CmsSite ContextSite
        {
            get
            {
                return CmsContext.ContextSite;
            }
        }

        public IModelMapper ModelMapper
        {
            get
            {
                return DependencyServiceLocator.Current.GetInstance<IModelMapper>();
            }
        }

        protected virtual CmsSiteAdminMapService SiteAdminMapService
        {
            get
            {
                if (_siteAdminMapService == null)
                {
                    _siteAdminMapService = new CmsSiteAdminMapService();
                }

                return _siteAdminMapService;
            }
        }

        protected virtual CmsUserInformationService UserInformationService
        {
            get
            {
                if (_userInformationService == null)
                {
                    _userInformationService = new CmsUserInformationService();
                }

                return _userInformationService;
            }
        }

        protected virtual CmsEntityMetaInformationService EntityMetaInformationService
        {
            get
            {
                if (_entityMetaInformationService == null)
                {
                    _entityMetaInformationService = new CmsEntityMetaInformationService();
                }

                return _entityMetaInformationService;
            }
        }

        #endregion Properties

        [HttpDelete]
        public virtual ActionResult DeleteAjax(int id)
        {
            ActionResult result = null;

            try
            {
                result = Json(_Delete(id) ? 1 : 0);
            }
            catch (Exception ex)
            {
                ControllerContext.HttpContext.Response.StatusCode = 500;
                result = Content(ex.Message, "text/html", Encoding.UTF8);
            }

            return result;
        }

        [HttpPost]
        public virtual ActionResult Delete(int id)
        {
            ActionResult result = null;

            try
            {
                _Delete(id);

                result = RedirectToAction("Index");
            }
            catch (Exception ex)
            {
                ControllerContext.HttpContext.Response.StatusCode = 500;
                result = Content(ex.Message, "text/html", Encoding.UTF8);
            }

            return result;
        }

        public virtual ActionResult MenuMap()
        {
            var nodes = SiteAdminMapService.FindAll();
            var firstLevelNodes = SiteAdminMapService.GetFirstLevelNodes(CmsContext.ContextUser);
            var absolutePath = Request.Url.AbsolutePath;

            var temp = firstLevelNodes.Select(p => new CmsAdminSitemapModel
            {
                Title = p.NodeTitle,
                Url = p.NodeUrl,
                IsSelected = SelectedNodeItem(false, absolutePath, p, nodes)
            });
            return PartialView(temp);
        }

        private bool SelectedNodeItem(bool initResultValue, string currentUrl, CmsSiteAdminMap item, IEnumerable<CmsSiteAdminMap> items)
        {
            var url = items.OrderByDescending(x => x.Level).FirstOrDefault(x => currentUrl.Contains(x.NodeUrl));
            if (url == null || url.Level == 0) return false;
            if (url.Level == 1)
            {
                if (item.NodeUrl == currentUrl) return true;
                return false;
            }

            initResultValue = SelectedNodeItem(initResultValue, items.FirstOrDefault(x => x.Id == url.ParentNodeId).NodeUrl, item, items);
            return initResultValue;
        }

        public virtual ActionResult SubNavigation(bool includeParent = true)
        {
            CmsAdminEntityTreeNode<CmsSiteAdminMap>[] data = null;

            var currentNode = GetCurrentAdminSection();

            if (currentNode != null && currentNode.RootInstance != null)
            {
                if (includeParent && currentNode.RootInstance.ParentNodeId.HasValue)
                {
                    var siteAdminMaps = GetFullCmsAdminMap();
                    var parent = siteAdminMaps.FirstOrDefault(p => p.Id == currentNode.RootInstance.ParentNodeId.Value);
                    if (parent != null && parent.Level != 0)
                    {
                        var parentTree = GetTreeNode(parent, siteAdminMaps, 1);
                        data = new[] { parentTree };
                        if (parentTree.NestedTreeNodes != null)
                        {
                            data = data.Concat(parentTree.NestedTreeNodes).ToArray();
                        }
                    }
                }

                if (data == null)
                {
                    data = new[] { currentNode };
                }

                if (currentNode.NestedTreeNodes != null)
                {
                    data = data.Concat(currentNode.NestedTreeNodes).ToArray();
                }
            }

            return PartialView(
                (data ?? new List<CmsAdminEntityTreeNode<CmsSiteAdminMap>>().ToArray())
                    .Where(p => p.RootInstance.IsVisible)
                    .Select(p => new CmsAdminSitemapModel
                    {
                        Title = p.RootInstance.NodeTitle,
                        Url = p.RootInstance.NodeUrl
                    }));
        }

        protected IList<CmsSiteAdminMap> GetFullCmsAdminMap()
        {
            return fullCmsAdminMap ??
                   (fullCmsAdminMap = SiteAdminMapService.FindAllForUser(CmsContext.ContextUser).ToList());
        }

        protected virtual bool _Delete(int id)
        {
            throw new NotImplementedException();
        }

        protected virtual CmsAdminEntityTreeNode<CmsSiteAdminMap> GetCurrentAdminSection()
        {
            CmsAdminEntityTreeNode<CmsSiteAdminMap> result = null;

            var data = GetFullCmsAdminMap();

            if (data != null)
            {
                var currentNode = data.FirstOrDefault(p => p.NodeUrl.Equals(HttpContext.Request.Path, StringComparison.OrdinalIgnoreCase));

                if (currentNode != null)
                {
                    result = GetTreeNode(currentNode, data, 1);
                }
            }

            return result ?? new CmsAdminEntityTreeNode<CmsSiteAdminMap>();
        }

        protected static CmsAdminEntityTreeNode<CmsSiteAdminMap> GetTreeNode(CmsSiteAdminMap cmsSiteAdminMap, IEnumerable<CmsSiteAdminMap> allCmsSiteAdminMaps)
        {
            return GetTreeNode(cmsSiteAdminMap, allCmsSiteAdminMaps, int.MaxValue);
        }

        protected static CmsAdminEntityTreeNode<CmsSiteAdminMap> GetTreeNode(CmsSiteAdminMap cmsSiteAdminMap, IEnumerable<CmsSiteAdminMap> allCmsSiteAdminMaps, int depth)
        {
            CmsAdminEntityTreeNode<CmsSiteAdminMap> result = null;

            if ((cmsSiteAdminMap != null) && (allCmsSiteAdminMaps != null) && (depth >= 0))
            {
                result = new CmsAdminEntityTreeNode<CmsSiteAdminMap>
                {
                    RootInstance = new CmsSiteAdminMap
                    {
                        Id = cmsSiteAdminMap.Id,
                        NodeTitle = cmsSiteAdminMap.NodeTitle,
                        NodeUrl = cmsSiteAdminMap.NodeUrl,
                        IsVisible = cmsSiteAdminMap.IsVisible,
                        IsSpecial = cmsSiteAdminMap.IsSpecial,
                        HasChildren = cmsSiteAdminMap.HasChildren,
                        ParentNodeId = cmsSiteAdminMap.ParentNodeId
                    },
                    NestedTreeNodes =
                        allCmsSiteAdminMaps
                            .Where(p => p.ParentNodeId == cmsSiteAdminMap.Id)
                            .Select(p => GetTreeNode(p, allCmsSiteAdminMaps, depth - 1))
                            .ToArray()
                };
            }

            return result;
        }

        internal void SetFolders(int? currentId = null)
        {
            ViewBag.Folders =
                new SelectList(new CmsMediaService().FindAllWithSubfolders().Where(p => p.Id != currentId.GetValueOrDefault(0))
                    .Select(e => new { e.Id, FolderName = e.FolderName.PadLeft(e.FolderName.Length + e.Level, '\u00a0') }), "Id", "FolderName");
        }
    }
}